#include <iostream>
#include <list>
#include <string>
using namespace std;

class PasteBoard
{
private:
    string words;
    PasteBoard() {}
public:
    static PasteBoard* getInstance() 
    {
        static PasteBoard* instance;
        if(instance==NULL) instance = new PasteBoard();
        return instance;
    }
    void push(string words) 
    {
        this->words += words;
    }
    string pop() 
    {
        string str = this->words;
        this->words = "";
        return str;
    }
};

class Command 
{
public:
	virtual ~Command() {}
	virtual void execute()=0;
};

class CutCmd: public Command
{
private:
    string words;
public:
    CutCmd(string words) 
    {
        this->words = words;
    }
    void execute() 
    {
        cout << "cut some words: " << words << endl;
        PasteBoard* pasteBoard = PasteBoard::getInstance();
        pasteBoard->push(words);
    }
};

class CopyCmd: public Command
{
private:
    string words;
public:
    CopyCmd(string words) 
    {
        this->words = words;
    }
    void execute() {
        cout << "copy some words: " << words << endl;
        PasteBoard* pasteBoard = PasteBoard::getInstance();
        pasteBoard->push(words);
    }
};

class PasteCmd: public Command
{
public:
    PasteCmd() {}
    void execute() 
    {
        PasteBoard* pasteBoard = PasteBoard::getInstance();
        string words = pasteBoard->pop();
        cout << "paste some words: " << words << endl;
    }
};

class Invoker 
{
private:
	list<Command*> cmds;
public:
	void addCommand(Command* command) 
    {
		cmds.push_back(command);
	}
	void delCommand(Command* command) 
    {
		cmds.remove(command);
	}
	void action() 
    {
		for(list<Command*>::iterator iter=cmds.begin(); iter!=cmds.end(); iter++) {
			(*iter)->execute();
		}
        cmds.clear();
	}
};

int main()
{
    Invoker* invoker = new Invoker();
    invoker->addCommand(new CutCmd("hello world! "));
    invoker->addCommand(new CutCmd("welcome to you. "));
    invoker->addCommand(new PasteCmd());
    invoker->action();

    invoker->addCommand(new CutCmd("hello world! "));
    CopyCmd* copyCmd = new CopyCmd("welcome to you. ");
    invoker->addCommand(copyCmd);
    invoker->addCommand(new CopyCmd("let's go! "));
    invoker->delCommand(copyCmd);
    invoker->addCommand(new PasteCmd());
    invoker->action();

    return 0;
}
